import json
from fastapi import FastAPI, Depends, HTTPException, UploadFile, File
from fastapi.staticfiles import StaticFiles
from sqlalchemy.orm import Session
from typing import List
from models import Invoice, InvoiceCreate, InvoiceResponse, PaginatedResponse
from database import get_db
import os
import shutil
import time
from baiduOCR.aip.ocr import AipOcr
from datetime import datetime
import logging
import tools.zip

app = FastAPI()
app.mount("/uploads", StaticFiles(directory="uploads"), name="uploads")
ocrConfig = {"appId":"120126867", "appKey":"LygyqNAg9EzlLjYGQNTl9BrZ", "secretKey":"KprPncjQlkgAl5T6Ol2p4qNfMIqzzcIR"}

logging.basicConfig()
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)

#### python -m uvicorn main:app --reload

@app.get("/invoices", response_model=PaginatedResponse[InvoiceResponse])
def get_invoices(
    pageNum: int = 1,
    limit: int = 100,
    invoice_code: str = None,
    buyer_name: str = None,
    seller_name: str = None,
    start_date: str = None,
    end_date: str = None,
    license_plate: str = None,
    db: Session = Depends(get_db)
):
    """获取发票列表
    支持以下查询条件：
    - invoice_code: 发票代码
    - buyer_name: 购买方名称
    - seller_name: 销售方名称
    - start_date/end_date: 开票日期范围 (格式: YYYY-MM-DD)
    - plate_number: 车牌号
    """
    skip = (pageNum - 1) * limit
    query = db.query(Invoice)

    # 动态添加查询条件
    if invoice_code:
        query = query.filter(Invoice.invoice_code == invoice_code)
    if buyer_name:
        query = query.filter(Invoice.buyer_name.like(f"%{buyer_name}%"))
    if seller_name:
        query = query.filter(Invoice.seller_name.like(f"%{seller_name}%"))
    if start_date and end_date:
        query = query.filter(Invoice.issue_date.between(start_date, end_date))
    if license_plate:
        query = query.filter(Invoice.license_plate.like(f"%{license_plate}%"))

    # 执行查询
    invoices = query.order_by(Invoice.invoice_code.asc()).limit(limit).offset(skip).all()
    total = query.count()
    totalPages = (total + limit - 1) // limit if limit > 0 else 1

    return {
        "data": invoices,
        "total": total,
        "page": pageNum,
        "limit": limit,
        "totalPages": totalPages
    }

@app.post("/invoices", response_model=InvoiceResponse)
def create_invoice(invoice: InvoiceCreate, db: Session = Depends(get_db)):
    """新增发票信息"""
    db_invoice = Invoice(**invoice.dict())
    db.add(db_invoice)
    db.commit()
    db.refresh(db_invoice)
    return db_invoice

@app.post("/invoices/{invoice_id}", response_model=InvoiceResponse)
def update_invoice(
    invoice_id: int,
    invoice: InvoiceCreate,
    db: Session = Depends(get_db)
):
    """修改发票信息"""
    print(invoice_id)
    db_invoice = db.query(Invoice).filter(Invoice.id == invoice_id).first()
    if not db_invoice:
        raise HTTPException(status_code=404, detail="Invoice not found")

    for key, value in invoice.dict().items():
        setattr(db_invoice, key, value)

    db.commit()
    db.refresh(db_invoice)
    return db_invoice


@app.delete("/invoices/{invoice_id}")
def delete_invoice(
    invoice_id: int,
    db: Session = Depends(get_db)
):
    """根据发票编号删除发票信息"""
    db_invoice = db.query(Invoice).filter(Invoice.id == invoice_id).first()
    if not db_invoice:
        raise HTTPException(status_code=404, detail="Invoice not found")

    db.delete(db_invoice)
    db.commit()
    return {"message": "Invoice deleted successfully"}

# 确保上传目录存在
UPLOAD_DIR = "uploads"
os.makedirs(UPLOAD_DIR, exist_ok=True)


def safe_get(data, keys, default=None):
    """安全获取嵌套字典的值"""
    try:
        for key in keys:
            data = data[key]
        return data if data is not None else default
    except (KeyError, IndexError, TypeError):
        return default

@app.post("/invoice/parse")
async def parse_invoice_pdf(file: UploadFile = File(...)):
    """
    处理前端上传的PDF发票文件
    1. 保存文件到服务器
    2. 解析PDF内容
    3. 返回解析结果
    """
    try:
        # 保存文件
        timestamp = int(time.time())
        print(timestamp)
        filepathname = str(timestamp)+".pdf"
        file_path = os.path.join(UPLOAD_DIR, filepathname)
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)

        # 读取文件内容
        with open(file_path, "rb") as pdf_file:
            file_data = pdf_file.read()

        ocr = AipOcr(ocrConfig["appId"], ocrConfig["appKey"], ocrConfig["secretKey"])
        invoiceData = ocr.multipleInvoicePdf(file_data)
        # invoiceData = '{"words_result": [{"result": {"AmountInWords": [{"word": "壹拾玖元贰角贰分"}], "TransportDeparture": [], "CommodityEndDate": [], "CommodityPrice": [{"row": "1", "word": "20201121"}], "InvoiceTag": [{"word": "通行费"}], "SellerRegisterNum": [{"word": "91510000709155317M"}], "TransportPlateNum": [], "Remarks": [{"word": "汇总开具"}], "CommodityTaxRate": [{"row": "1", "word": "3%"}], "ServiceType": [{"word": "交通"}], "InvoiceCodeConfirm": [{"word": "051001700112"}], "InvoiceCode": [{"word": "051001700112"}], "TransportType": [{"row": "1", "word": "○"}], "SubTotalTax": [], "PurchaserRegisterNum": [{"word": "91510903MA6260NF1E"}], "InvoiceTypeOrg": [{"word": "四川增值税电子普通发票"}], "Agent": [{"word": "否"}], "AmountInFiguers": [{"word": "19.22"}], "TransportArrival": [], "City": [], "CommodityAmount": [{"row": "1", "word": "18.66"}], "PurchaserName": [{"word": "四川三足科技有限公司"}], "CommodityType": [], "Province": [{"word": "四川省"}], "PassengName": [], "CurrentPage": [], "PassengOrigin": [], "InvoiceNumDigit": [], "CommodityTax": [{"row": "1", "word": "0.56"}], "PassengClass": [], "Payee": [{"word": "徐霞"}], "SubTotalAmount": [], "PassengDestination": [], "InvoiceNumConfirm": [{"word": "98778004"}], "CommodityStartDate": [], "CommodityVehicleType": [], "NoteDrawer": [{"word": "张俊蕾"}], "SellerAddress": [{"word": "成都市武侯区武侯祠大街180号028-84121625"}], "CommodityNum": [{"row": "1", "word": "20201121"}], "TotalPage": [], "MachineCode": [{"word": "499099655642"}], "SellerBank": [{"word": "成都建设银行股份有限公司成都南郊支行51001875136050366310"}], "TotalTax": [{"word": "0.56"}], "CheckCode": [{"word": "14255625208635483357"}], "InvoiceDate": [{"word": "2020年12月23日"}], "PassengDate": [], "Password": [{"word": "0395*4+7264391/3*7894-90*>*<7*0/<98742508<11342/05+566<-+9-83><<98/2079811430/-9*<738>/*/-<620181>519396*0/5>3>"}], "OnlinePay": [], "PurchaserBank": [], "Checker": [{"word": "徐霞"}], "PassengVehicleType": [], "TotalAmount": [{"word": "18.66"}], "TransportCargoInfo": [], "InvoiceType": [{"word": "电子普通发票"}], "SheetNum": [], "PurchaserAddress": [], "CommodityPlateNum": [], "CommodityUnit": [{"row": "1", "word": "客车"}], "CommodityName": [{"row": "1", "word": "*经营租赁*通行费"}], "SellerName": [{"word": "四川成南高速公路有限责任公司"}], "PassengIdNum": [], "InvoiceNum": [{"word": "98778004"}]}, "top": 0, "left": 0, "probability": 0.9861998558, "width": 846, "type": "vat_invoice", "height": 543}], "words_result_num": 1, "pdf_file_size": 1, "log_id": 1969439873925796312}'
        # invoiceData = json.loads(invoiceData)
        invoiceData = invoiceData["words_result"]
        print(invoiceData)

        issue_date = safe_get(invoiceData, [0, 'result', 'InvoiceDate', 0, 'word'], "")
        issue_date = issue_date.replace("年", "-").replace("月", "-").replace("日", "")
        issue_date = datetime.strptime(issue_date, "%Y-%m-%d").strftime("%Y-%m-%d")

        # pass_start_date = safe_get(invoiceData, [0, 'result', 'CommodityStartDate', 0, 'word'], "")
        # pass_start_date = pass_start_date.replace("年", "-").replace("月", "-").replace("日", "")
        # pass_start_date = datetime.strptime(pass_start_date, "%Y-%m-%d").strftime("%Y-%m-%d")


        # pass_end_date = safe_get(invoiceData, [0, 'result', 'CommodityEndDate', 0, 'word'], "")
        # pass_end_date = pass_end_date.replace("年", "-").replace("月", "-").replace("日", "")
        # pass_end_date = datetime.strptime(pass_end_date, "%Y-%m-%d").strftime("%Y-%m-%d")


        rst = {
            "invoice_code":safe_get(invoiceData, [0, 'result', 'InvoiceCode', 0, 'word'], ""),
            "invoice_number":safe_get(invoiceData, [0, 'result', 'InvoiceNum', 0, 'word'], ""),

            "issue_date":issue_date,

            "buyer_name":safe_get(invoiceData, [0, 'result', 'PurchaserName', 0, 'word'], ""),
            "buyer_tax_id":safe_get(invoiceData, [0, 'result', 'PurchaserRegisterNum', 0, 'word'], ""),
            "buyer_address":safe_get(invoiceData, [0, 'result', 'PurchaserAddress', 0, 'word'], ""),
            "buyer_phone":safe_get(invoiceData, [0, 'result', 'PurchaserPhone', 0, 'word'], ""),
            "buyer_bank":safe_get(invoiceData, [0, 'result', 'PurchaserBank', 0, 'word'], ""),
            "buyer_account":safe_get(invoiceData, [0, 'result', 'PurchaserAccount', 0, 'word'], ""),
            "seller_name":safe_get(invoiceData, [0, 'result', 'SellerName', 0, 'word'], ""),
            "seller_tax_id":safe_get(invoiceData, [0, 'result', 'SellerRegisterNum', 0, 'word'], ""),
            "seller_address":safe_get(invoiceData, [0, 'result', 'SellerAddress', 0, 'word'], ""),
            "seller_bank":safe_get(invoiceData, [0, 'result', 'SellerBank', 0, 'word'], ""),
            "item_name":safe_get(invoiceData, [0, 'result', 'CommodityName', 0, 'word'], ""),
            "license_plate":safe_get(invoiceData, [0, 'result', 'CommodityPlateNum', 0, 'word'], ""),
            "vehicle_type":safe_get(invoiceData, [0, 'result', 'CommodityVehicleType', 0, 'word'], ""),

            # pass_start_date=pass_start_date,
            # pass_end_date=pass_end_date,
            
            "amount":safe_get(invoiceData, [0, 'result', 'CommodityAmount', 0, 'word'], 0.0),
            "tax_rate":safe_get(invoiceData, [0, 'result', 'CommodityTaxRate', 0, 'word'], 0.0),
            "tax_amount":safe_get(invoiceData, [0, 'result', 'CommodityTax', 0, 'word'], 0.0),
            "total_price":safe_get(invoiceData, [0, 'result', 'AmountInFiguers', 0, 'word'], 0.0),
            "remarks":safe_get(invoiceData, [0, 'result', 'Remarks', 0, 'word'], ""),
            "payee":safe_get(invoiceData, [0, 'result', 'Payee', 0, 'word'], ""),
            "reviewer":safe_get(invoiceData, [0, 'result', 'Checker', 0, 'word'], ""),
            "issuer":safe_get(invoiceData, [0, 'result', 'NoteDrawer', 0, 'word'], ""),
            "source_file_path":file_path,
        }

        # 去除百分号并转换为浮点数
        rst["tax_rate"] = float(rst["tax_rate"].rstrip('%')) / 100.0
        
        return {
            "status": "success",
            "filename": file.filename,
            "filepath": file_path,
            "invoiceData": rst
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"PDF解析失败: {str(e)}")


@app.post("/invoice/zipparse")
async def parse_invoice_zip(file: UploadFile = File(...)):
    """
    处理前端上传的zip压缩包
    1. 保存文件到服务器
    2. 解析ZIP内容
    3. 返回解析结果
    """
    try:
        # 保存文件
        timestamp = int(time.time())
        print(timestamp)
        filepathname = str(timestamp)+".zip"
        file_path = os.path.join(UPLOAD_DIR+"/zip", filepathname)
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)

        return tools.zip.main(file_path, UPLOAD_DIR+"/zip/"+str(timestamp))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"ZIP解析失败: {str(e)}")
     

@app.post("/invoicesByZip", response_model=InvoiceResponse)
def invoicesByZip(fileList: List[str], db: Session = Depends(get_db)):
    """新增发票信息通过解压的ZIP文件"""
    for file in fileList:
        try:
            # 保存文件
            timestamp = int(time.time())
            print(timestamp,file)
            filepathname = str(timestamp)+".pdf"
            file_path = os.path.join(UPLOAD_DIR, filepathname)
            shutil.copy2(UPLOAD_DIR+"/zip/"+file, file_path)
            time.sleep(1)
            invoicezip = Invoice()
            invoicezip.source_file_path = file_path
            invoicezip.invoice_code = timestamp
            invoicezip.invoice_number = timestamp
            invoicezip.issue_date = datetime.now()
            invoicezip.buyer_name = "批量导入待编辑解析确认"
            invoicezip.buyer_tax_id = "批量导入待编辑解析确认"
            invoicezip.seller_name = "批量导入待编辑解析确认"
            invoicezip.seller_tax_id = "批量导入待编辑解析确认"
            invoicezip.amount = 0
            invoicezip.tax_rate = 0
            invoicezip.tax_amount = 0
            invoicezip.total_price = 0
            invoicezip.issuer = "批量导入待编辑解析确认"
            db.add(invoicezip)
            db.commit()
            # db.refresh(invoicezip)
            return invoicezip
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"发票批量保存失败: {str(e)}")

@app.post("/reparseInvoice")
def reparseInvoice(invoice_id: List[int], db: Session = Depends(get_db)):
    query = db.query(Invoice)
    invoice = query.where(Invoice.id == invoice_id[0]).first()
    print(invoice.source_file_path)
    if not invoice:
        raise HTTPException(status_code=500, detail="未找到当前发票")
    elif not invoice.source_file_path:
        raise HTTPException(status_code=500, detail="发票源文件路径不存在")
    elif not os.path.exists(invoice.source_file_path):
        raise HTTPException(status_code=500, detail="发票源文件不存在")
    
    try:
        # 读取文件内容
        with open(invoice.source_file_path, "rb") as pdf_file:
            file_data = pdf_file.read()

        ocr = AipOcr(ocrConfig["appId"], ocrConfig["appKey"], ocrConfig["secretKey"])
        invoiceData = ocr.multipleInvoicePdf(file_data)

        invoiceData = invoiceData["words_result"]
        print(invoiceData)
        issue_date = safe_get(invoiceData, [0, 'result', 'InvoiceDate', 0, 'word'], "")
        issue_date = issue_date.replace("年", "-").replace("月", "-").replace("日", "")
        issue_date = datetime.strptime(issue_date, "%Y-%m-%d").strftime("%Y-%m-%d")
        rst = {
            "invoice_code":safe_get(invoiceData, [0, 'result', 'InvoiceCode', 0, 'word'], "noValue"),
            "invoice_number":safe_get(invoiceData, [0, 'result', 'InvoiceNum', 0, 'word'], "noValue"),

            "issue_date":issue_date,

            "buyer_name":safe_get(invoiceData, [0, 'result', 'PurchaserName', 0, 'word'], "noValue"),
            "buyer_tax_id":safe_get(invoiceData, [0, 'result', 'PurchaserRegisterNum', 0, 'word'], "noValue"),
            "buyer_address":safe_get(invoiceData, [0, 'result', 'PurchaserAddress', 0, 'word'], ""),
            "buyer_phone":safe_get(invoiceData, [0, 'result', 'PurchaserPhone', 0, 'word'], ""),
            "buyer_bank":safe_get(invoiceData, [0, 'result', 'PurchaserBank', 0, 'word'], ""),
            "buyer_account":safe_get(invoiceData, [0, 'result', 'PurchaserAccount', 0, 'word'], ""),
            "seller_name":safe_get(invoiceData, [0, 'result', 'SellerName', 0, 'word'], "noValue"),
            "seller_tax_id":safe_get(invoiceData, [0, 'result', 'SellerRegisterNum', 0, 'word'], "noValue"),
            "seller_address":safe_get(invoiceData, [0, 'result', 'SellerAddress', 0, 'word'], ""),
            "seller_bank":safe_get(invoiceData, [0, 'result', 'SellerBank', 0, 'word'], ""),
            "item_name":safe_get(invoiceData, [0, 'result', 'CommodityName', 0, 'word'], ""),
            "license_plate":safe_get(invoiceData, [0, 'result', 'CommodityPlateNum', 0, 'word'], ""),
            "vehicle_type":safe_get(invoiceData, [0, 'result', 'CommodityVehicleType', 0, 'word'], ""),
            "amount":safe_get(invoiceData, [0, 'result', 'CommodityAmount', 0, 'word'], 0.0),
            "tax_rate":safe_get(invoiceData, [0, 'result', 'CommodityTaxRate', 0, 'word'], 0.0),
            "tax_amount":safe_get(invoiceData, [0, 'result', 'CommodityTax', 0, 'word'], 0.0),
            "total_price":safe_get(invoiceData, [0, 'result', 'AmountInFiguers', 0, 'word'], 0.0),
            "remarks":safe_get(invoiceData, [0, 'result', 'Remarks', 0, 'word'], ""),
            "payee":safe_get(invoiceData, [0, 'result', 'Payee', 0, 'word'], ""),
            "reviewer":safe_get(invoiceData, [0, 'result', 'Checker', 0, 'word'], ""),
            "issuer":safe_get(invoiceData, [0, 'result', 'NoteDrawer', 0, 'word'], "noValue"),
            "source_file_path":invoice.source_file_path,
        }

        print(rst)

        # 去除百分号并转换为浮点数
        rst["tax_rate"] = float(rst["tax_rate"].rstrip('%')) / 100.0
        
        return {
            "status": "success",
            "filename": "No importants of name",
            "filepath": invoice.source_file_path,
            "invoiceData": rst
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"PDF解析失败: {str(e)}")